package utils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;

public class ArrUtils {
    /**
     * 生成随机长度的随机数组, 数组长度区间[0,bound), 数组元素取值区间[0,bound)
     *
     * @param bound size和元素边界根据此参数生成
     * @return 返回生成的数组
     */
    public static int[] generateArr(int bound) {
        Random ran = new Random();
        bound = Math.abs(bound);
        int[] arr = new int[ran.nextInt(bound)];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = ran.nextInt(bound);
        }
        return arr;
    }

    /**
     * 生成数组
     *
     * @param size  自定义数组size
     * @param bound 数组元素取值边界 [0,bound)
     * @return 返回生成的数组
     */
    public static int[] generateArr(int size, int bound) {
        Random ran = new Random();
        int[] arr = new int[size];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = ran.nextInt(bound);
        }
        return arr;
    }

    //需求: 验证是否正确; 列出时间消耗对比
    public static void execute(Class clazz, String methodName) {
        //1, 获取带注解的方法: 目的获取参数
        Method method = null;
        Method[] methods = clazz.getMethods();
        for (Method m : methods) {
            if (m.getName().equals(methodName)) {
                method = m;
                break;
            }
        }
        //method = clazz.getDeclaredMethod(methodName);

        Perfomance perfomance = method.getAnnotation(Perfomance.class);
        int times = perfomance.times();
        int arrLength = perfomance.arrLength();
        int elementBound = perfomance.elementBound();


        ArrayList<Long> executeTimes1 = new ArrayList<>(arrLength);
        ArrayList<Long> executeTimes2 = new ArrayList<>(arrLength);
        try {
            //执行测试
            boolean isSuccess = true;
            int[] errCase = null;
            int[] resultCase = null;
            for (int i = 0; i < times; i++) {
                int[] arr1 = generateArr(arrLength, elementBound);
                int[] arr2 = arr1.clone();
                errCase = arr1; //用例测试不通过备用
                //系统排序执行及用时
                long start = System.currentTimeMillis();
                Arrays.sort(arr1);
                long end = System.currentTimeMillis();
                executeTimes1.add(end - start);

                //新算法排序执行及用时
                start = System.currentTimeMillis();

                method.invoke(null, arr2);
                end = System.currentTimeMillis();
                executeTimes2.add(end - start);
                resultCase = arr2;
                for (int m = 0; m < arrLength; m++) {
                    if (arr1[m] != arr2[m]) {
                        isSuccess = false;
                        break;
                    }
                }
            }
            //
            if (isSuccess) {
                //执行统计
                Long sum1 = 0L;
                Long sum2 = 0L;
                for (int i = 0; i < times; i++) {
                    sum1 += executeTimes1.get(i);
                    sum2 += executeTimes2.get(i);
                }
                System.out.println("Arrays.sort平均用时: " + sum1 / arrLength);
                System.out.println("新算法平均用时: " + sum2 / arrLength);
            } else {
                //打印报错信息
                System.out.println("未通过测试的用例:");
                printArr(errCase);
                System.out.println("新算法结果:");
                printArr(resultCase);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * 遍历打印数组
     *
     * @param arr 待打印的数组
     */
    public static void printArr(int[] arr) {
        if (arr == null) {
            System.out.println("Array is null!");
            return;
        }
        System.out.println("Start Print: -------------------------");
        for (int i : arr) {
            System.out.print(i + " ");
        }
        System.out.println("\nEnd:       -------------------------");
    }


}
